﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using WCS_Service.DomianService.Interface;
using WCS_Service.DomianService.Models;
using WCS_Utility.ConstString;
using Serilog;
using Quartz;
using System.Buffers;
using System.Net.NetworkInformation;
using WCS_Quartz_Task;
using WCS_Service.Enums;
using Autofac;
using Newtonsoft.Json;
using System.Collections;
using WCS_Entity.Model;
using WCS_Service.ProtocolServices.Interface;
using WCS_Entity.Prorocol;
using System.Collections.Concurrent;
using WCS_Utility.Extensions;
using WCS_Utility.Helper;
using Autofac.Core;
using System.Net.Security;

namespace WCS_Service.DomianService.ComDomainService
{
    public class EasyTcpCommunication : IComBaseDomainManage
    {
        #region 属性
        public bool IsConnected { get; private set; } //客户端是否已经连接上服务

        private Socket _socket;  //客户端本地套接字

        private Pipe _pipe;
        private PipeReader _pipeReader => _pipe.Reader;
        private PipeWriter _pipeWriter => _pipe.Writer;

        private CancellationTokenSource _lifecycleTokenSource; //整个客户端存活的token
        private CancellationTokenSource _receiveDataTokenSource;//客户端获取数据的token
        private readonly EasyTcpClientOptions _options = new();//客户端总配置
        public IPEndPoint RemoteEndPoint { get; private set; } //服务端的终结点
        public IPEndPoint LocalEndPoint { get; private set; } //客户端本地的终结点

        private NetworkStream _networkStream;

        private Task _dataReceiveTask = null;
        private Task _processDataTask = null;

        private IPackageFilter _receivePackageFilter = new FixedHeaderPackageFilter(2+2,2, 2); //接收数据包的拦截处理器

        private IPAddress _serverIpAddress = null; //服务端的ip地址

        private string heartBeatMsg = ConstStringData.HeartBeatMsg;

        private readonly IQuartzJobProcess _quartzJobProcess;
        private readonly IComponentContext _componentContext;
        public bool IsDisposed { get; private set; }

        private List<byte> msgHeart = new List<byte>() { 0xAB,0x66};
        #region 接口公共属性
        private string gengricMsg = "";
        //通信基础参数
        public string comPara { get; set; }
        private TcpComParaModel tcpComParaModel = new TcpComParaModel();
        public IProtocolService protocolService { get; set; }
        //协议配置报文
        public List<ProtocolEntity> protocolPara { get; set; } = new List<ProtocolEntity>();
        public string serviceName { get; set; }
        public int autoEquipmentId { get; set; }
        public string equipmentType { get; set; }
        public string areaCode { get; set; }
        //协议内容
        public ConcurrentDictionary<string, ProtocolModel> protocolMsgList { get; set; } = new ConcurrentDictionary<string, ProtocolModel>();

        //接收事件
        public event Func<ClientDataReceiveEventArgs, Task> ReciveChange;
        //断开连接事件
        public event Func<ClientSideDisConnectEventArgs, Task> ComDisConnectEvent;
        #endregion
        #endregion

        public EasyTcpCommunication(IComponentContext componentContext, IQuartzJobProcess quartzJobProcess)
        {
            _componentContext = componentContext;
            _quartzJobProcess = quartzJobProcess;
        }
        /// <summary>
        /// 初期化协议服务
        /// </summary>
        /// <returns></returns>
        private void InitProtocolServiceAsync()
        {
            if (protocolService is null)
            {
                return;
            }
            ReciveChange += protocolService.ReceiveMsgAsync;
        }
        public async Task<bool> InitService()
        {

            if (string.IsNullOrEmpty(comPara))
            {
                return false;
            }
            tcpComParaModel = JsonConvert.DeserializeObject<TcpComParaModel>(comPara);
            if (tcpComParaModel is null)
            {
                return false;
            }
            if (string.IsNullOrEmpty(tcpComParaModel.ip))
            {
                Log.Error($"TCP设备Ip错误{tcpComParaModel.ip}");
                return false;
            }

            if (tcpComParaModel.port > 65535 || tcpComParaModel.port <= 0)
            {
                Log.Error($"TCP设备端口错误{tcpComParaModel.port}");
                return false;
            }
            _serverIpAddress = IPAddress.TryParse(tcpComParaModel.ip, out var tempAddress) ?
                    tempAddress : Dns.GetHostEntry(tcpComParaModel.ip).AddressList[0];
            RemoteEndPoint = new IPEndPoint(_serverIpAddress, tcpComParaModel.port);
            LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);
            IsConnected = false;
            return true;
        }

        public async Task<bool> ConnectAsync()
        {
            try
            {
                if (IsConnected)
                    return true;
                if (!await InitService())
                {
                    return false;
                }
                _socket = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                if (_options.KeepAlive)
                    _socket.SetKeepAlive(_options.KeepAliveIntvl, _options.KeepAliveTime, _options.KeepAliveProbes);
                _socket.NoDelay = false;
                _pipe = new Pipe(new PipeOptions(pauseWriterThreshold: int.MaxValue));
                _lifecycleTokenSource = new CancellationTokenSource();
                int retryTimes = 0;
                while (retryTimes <= _options.ConnectRetryTimes)
                {
                    try
                    {
                        retryTimes++;
                        CancellationTokenSource connectTokenSource = new CancellationTokenSource();
                        connectTokenSource.CancelAfter(_options.ConnectTimeout);
                        await _socket.ConnectAsync(RemoteEndPoint, connectTokenSource.Token);
                        _networkStream = new NetworkStream(_socket);
                        _networkStream.ReadTimeout = _options.ReadTimeout;
                        _networkStream.WriteTimeout = _options.WriteTimeout;
                        break;
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            await _socket.DisconnectAsync(true);
                        }
                        catch
                        {

                        }
                        Log.Error($"连接{retryTimes}次失败:{ex}");
                        if (_options.ConnectRetryTimes < retryTimes)
                            throw;
                        else
                        {
                            continue;
                        }
                    }
                }
            }
            catch (TaskCanceledException)
            {
                Log.Error($"设备连接取消因为超时");
                return false;
            }
            catch (OperationCanceledException)
            {
                Log.Error($"设备连接超时");
                return false;
            }
            catch (Exception ex)
            {
                Log.Error($"设备连接异常{ex.ToString()}");
                return false;
            }

            _receiveDataTokenSource = new CancellationTokenSource();
            IsConnected = true;
            CancellationTokenSource ctx = CancellationTokenSource.CreateLinkedTokenSource(_lifecycleTokenSource.Token, _receiveDataTokenSource.Token);
            _processDataTask =
                Task.Factory.StartNew(ReadPipeAsync, _lifecycleTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current);
            _dataReceiveTask = Task.Factory.StartNew(ReceiveDataAsync,
                ctx.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current);
            //处理协议内容
            var initFlag = await InitProtocolMsgAsync();
            if (!initFlag)
            {
                await DisConnectAsync();
                return false;
            }
            InitProtocolServiceAsync();
            //启动心跳
            await SendHeartbeatAsync();
            return true;
        }
        internal async Task ReadPipeAsync()
        {
            while (!_lifecycleTokenSource.Token.IsCancellationRequested)
            {
                ReadResult result = await _pipeReader.ReadAsync();
                ReadOnlySequence<byte> buffer = result.Buffer;
                ReadOnlySequence<byte> data;
                do
                {
                    if (_receivePackageFilter != null)
                    {
                        data = _receivePackageFilter.ResolvePackage(ref buffer);
                    }
                    else
                    {
                        data = buffer;
                        buffer = buffer.Slice(data.Length);
                    }

                    if (!data.IsEmpty)
                    {
                        ReciveChange?.Invoke(new ClientDataReceiveEventArgs(data.ToArray()));
                    }
                }
                while (!data.IsEmpty && buffer.Length > 0);
                _pipeReader.AdvanceTo(buffer.Start);
            }

            _pipeReader.Complete();
        }

        /// <summary>
        /// 客户端循环读取数据
        /// </summary>
        /// <returns></returns>
        private async Task ReceiveDataAsync()
        {
            DisConnectReason disConnectReason = default;
            while (!_receiveDataTokenSource.Token.IsCancellationRequested)
            {
                if (IsDisposed)
                    break;
                try
                {
                    if (!_socket.CheckConnectProcess())
                    {
                        Log.Error($"Tcp通信断开");
                        await DisConnectAsync();
                        await ConnectAsync();
                        return;
                    }
                    Memory<byte> buffer = _pipeWriter.GetMemory(_options.BufferSize);
                    int readCount = 0;
                    if (_networkStream is not null)
                        readCount = await _networkStream.ReadAsync(buffer, _lifecycleTokenSource.Token).ConfigureAwait(false);

                    if (readCount > 0)
                    {
                        var data = buffer.Slice(0, readCount);
                        _pipeWriter.Advance(readCount);
                    }
                    else
                    {
                        if (!IsConnecting())
                        {
                            throw new SocketException();
                        }
                    }

                    FlushResult result = await _pipeWriter.FlushAsync().ConfigureAwait(false);
                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
                catch (TaskCanceledException)
                {
                    Log.Error($"TCP接收任务被取消");
                    disConnectReason = DisConnectReason.Normol;
                    break;
                }
                catch (Exception ex)
                {
                    Log.Error($"Tcp IP{RemoteEndPoint.Address}接收数据异常{ex}");
                    if (!_socket.CheckConnectProcess())
                    {
                        Log.Error($"Tcp通信断开");
                        await DisConnectAsync();
                        await ConnectAsync();
                        return;
                    }
                    if (ex is SocketException || ex is IOException)
                    {
                        disConnectReason = DisConnectReason.ServerDown;
                    }
                    else
                    {
                        disConnectReason = DisConnectReason.UnKnown;
                    }
                    break;
                }
            }

            _pipeWriter.Complete();
            await DisConnectInternalAsync(disConnectReason);
        }
        private bool IsConnecting()
        {
            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            var ss = ipProperties.GetActiveTcpConnections();
            TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections()
                .Where(x => x.LocalEndPoint.Equals(LocalEndPoint) && x.RemoteEndPoint.Equals(RemoteEndPoint)).ToArray();

            if (tcpConnections != null && tcpConnections.Length > 0)
            {
                TcpState stateOfConnection = tcpConnections.First().State;
                if (stateOfConnection == TcpState.Established)
                {
                    return true;
                }
            }

            return false;
        }
        /// <summary>
        /// 客户端断连
        /// </summary>
        public async Task DisConnectAsync()
        {
            await DisConnectInternalAsync(DisConnectReason.Normol);
        }
        /// <summary>
        /// 断开重新连接
        /// </summary>
        /// <returns></returns>
        public async Task ReConnectAsync()
        { 
            
        }
        /// <summary>
        /// 客户端断连
        /// </summary>
        private async Task DisConnectInternalAsync(DisConnectReason disConnectReason)
        {
            if (!IsConnected)
            {
                Log.Information($"设备通信连接断开{RemoteEndPoint}");
                return;
            }

            _receiveDataTokenSource?.Cancel();
            _lifecycleTokenSource?.Cancel();
            await _dataReceiveTask;
            await _processDataTask;
            _socket?.Close();
            _socket?.Dispose();
            _dataReceiveTask?.Dispose();
            _processDataTask?.Dispose();
            IsConnected = false;
            ComDisConnectEvent?.Invoke(new ClientSideDisConnectEventArgs(disConnectReason: disConnectReason, equipmentType, autoEquipmentId));

            Log.Information($"设备通信连接断开{RemoteEndPoint}");
        }

        #region 发送心跳
        /// <summary>
        /// 发送心跳
        /// </summary>
        /// <returns></returns>
        public async Task SendHeartbeatAsync()
        {
            var jobDetail = JobBuilder.Create<OpticalJob>().WithIdentity(ConstStringData.OpticalHeartbeat + autoEquipmentId,
                     ConstStringData.OpticalHeartbeat).Build();
            jobDetail.JobDataMap.Put("sendHeart", SendHeartbeat);
            var trigger = TriggerBuilder.Create()
                                        .WithSimpleSchedule(m =>
                                        {
                                            m.WithIntervalInSeconds(20).RepeatForever();
                                        })
                                        .Build();

            //添加心跳任务
            await _quartzJobProcess.AddJobAsync(jobDetail, trigger);
        }

        /// <summary>
        /// 发送心跳包
        /// </summary>
        public async Task SendHeartbeat()
        {
            try
            {
                if (!IsConnected)
                {
                    return;
                }
                await SendAsync(heartBeatMsg);
            }
            catch (Exception ex)
            {
                Log.Error($"心跳发送异常{ex.Message}");
                return;
            }
        }
        #endregion

        #region 发送
        public async Task<bool> SendAsync(string info)
        {
            if (!_socket.CheckConnectProcess())
            {
                Log.Error($"Tcp通信断开");
                await DisConnectAsync();
                var flag = await ConnectAsync();
                if (!flag) return false;
            }
            byte[] data = Encoding.UTF8.GetBytes(info);
            if (data == null || data.Length < 1)
            {
                Log.Error($"发送数据长度异常!");
                return false;
            }
            List<byte> sendData = new();
            var heard = BitConverter.GetBytes((ushort)data.Length);
            sendData.AddRange(msgHeart);
            sendData.AddRange(heard);
            sendData.AddRange(data);
            if (!IsConnected)
            {
                Log.Error($"设备未连接发送失败!");
                return false;
            }
            return await SendInternalAsync(sendData.ToArray());
        }
        private async Task<bool> SendInternalAsync(Memory<byte> data)
        {
            int bytesRemaining = data.Length;
            int index = 0;

            try
            {
                while (bytesRemaining > 0)
                {
                    Memory<byte> needSendData = null;
                    if (bytesRemaining >= 4 * 1024)
                    {
                        needSendData = data.Slice(index, 4 * 1024);
                    }
                    else
                    {
                        needSendData = data.Slice(index, bytesRemaining);
                    }
                    await _networkStream.WriteAsync(needSendData, _lifecycleTokenSource.Token);
                    index += needSendData.Length;
                    bytesRemaining -= needSendData.Length;
                }
                return true;
            }
            catch (IOException ex)
            {
                ComDisConnectEvent?.Invoke(new ClientSideDisConnectEventArgs(DisConnectReason.ServerDown,equipmentType,autoEquipmentId));
                Log.Error($"Tcp发送异常{ex.ToString()}");

                return false;
            }
            catch (Exception ex)
            {
                if (ex is TaskCanceledException || ex is OperationCanceledException)
                {
                    Log.Error($"Tcp发送任务取消");
                }

                Log.Error($"Tcp发送异常{ex.ToString()}");

                return false;
            }
        }
        #endregion
        public async Task DisposeAsync()
        {
            if (!IsDisposed)
            {
                await InternalDispose();
            }
        }
        private async Task InternalDispose()
        {
            _lifecycleTokenSource?.Cancel();
            await _processDataTask;
            _socket?.Dispose();
            _networkStream?.Close();
            _networkStream?.Dispose();
            IsDisposed = true;
        }
        #region 协议处理
        private async Task<bool> InitProtocolMsgAsync()
        {
            var serialNetInfo = protocolPara.FirstOrDefault(p => p.isSerialNet);
            if (serialNetInfo is not null)
            {
                return await SerialNetMsgProcessAsync();
            }
            //协议通用字段处理
            var gengricInfo = protocolPara.Where(p => string.IsNullOrEmpty(p.messageType))?.ToList();
            if (gengricInfo is not null && gengricInfo.Any())
            {
                await GengricMsgProcessAsync(gengricInfo);
            }
            var msgInfo = protocolPara.Where(m => !string.IsNullOrEmpty(m.messageType))?.GroupBy(msg => msg.messageType).ToList();
            if (msgInfo is null)
            {
                return false;
            }
            List<Task<bool>> processFlagList = new List<Task<bool>>();
            msgInfo.ForEach(info =>
            {
                processFlagList.Add(ProtocolMsgProcessAsync(info));
            });
            await Task.WhenAll(processFlagList);
            var flags = processFlagList.Select(p => p.Result).ToList();
            foreach (var item in flags)
            {
                if (!item)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 透传报文的处理
        /// </summary>
        /// <returns></returns>
        private async Task<bool> SerialNetMsgProcessAsync()
        {
            return await Task.Run(() =>
            {
                if (protocolPara.Count != 1)
                {
                    Log.Error($"Protocol内容配置错误，透传类型报文只需配置一条!");
                    return false;
                }
                var protocolInfo = protocolPara.FirstOrDefault();
                if (protocolInfo is null)
                {
                    Log.Error($"Protocol内容获取失败!");
                    return false;
                }
                if (!_componentContext.TryResolveKeyed<IProtocolService>(protocolInfo.protocolType, out IProtocolService protocolModel))
                {
                    Log.Error($"protocol协议类型不支持!");
                    return false;
                }
                if (protocolModel is null)
                {
                    Log.Error($"protovolService获取失败!");
                    return false;
                }
                protocolModel.isSerialNet = true;
                protocolModel.equipmentId = autoEquipmentId;
                protocolService = protocolModel;
                return true;
            });
        }

        private async Task GengricMsgProcessAsync(List<ProtocolEntity> infos)
        {
            await Task.Run(() =>
            {
                var infoList = infos.OrderBy(info => info.fieldIndex);
                int preIndex = 0;
                StringBuilder msg = new StringBuilder();
                foreach (var info in infoList)
                {
                    if (CommonHelper.ContinuousNumberChecker(preIndex, info.fieldIndex, out int differenceNum))
                    {
                        msg.Append(info.fieldInfo + ',');
                        preIndex++;
                    }
                    else
                    {
                        msg.Append(CommonHelper.GetInsertChar(differenceNum - 1, ConstStringData.InsertStringInfo));
                        msg.Append(info.fieldInfo + ',');
                        preIndex += differenceNum - 1;
                    }
                }
                gengricMsg = msg.ToString();
            });
        }

        /// <summary>
        /// 协议报文处理
        /// </summary>
        /// <param name="infos"></param>
        /// <returns></returns>
        private async Task<bool> ProtocolMsgProcessAsync(IGrouping<string, ProtocolEntity> infos)
        {
            if (!infos.Any())
            {
                return false;
            }
            List<Task<ProtocolModel>> dataMsg = new List<Task<ProtocolModel>>();

            //根据报文发送者分组
            var senderMsgList = infos.GroupBy(i => i.sender).ToList();
            senderMsgList.ForEach(s =>
            {
                dataMsg.Add(ProcotolMsgSenderProcessAsync(infos.Key, s.Key, s));
            });
            await Task.WhenAll(dataMsg);
            var protocolList = dataMsg.Select(s => s.Result)?.ToList();

            protocolList?.ForEach(p =>
            {
                protocolMsgList.TryAdd(string.Join('-', infos.Key, p.sender), p);
            });
            return true;
        }
        private async Task<ProtocolModel> ProcotolMsgSenderProcessAsync(string msgType, string sender, IGrouping<string, ProtocolEntity> infos)
        {
            ProtocolModel protocolModel = new ProtocolModel();
            protocolModel.sender = sender;
            //protocolModel.functionCode = infos.Where(i => i.isFunctionCode).FirstOrDefault()?.fieldInfo.Split(":").Last();

            var dataMsgList = infos.GroupBy(i => i.fieldIndex).ToList();
            List<Task<MsgDataInfoModel>> dataMsgInfos = new List<Task<MsgDataInfoModel>>();
            dataMsgList.ForEach(d =>
            {
                dataMsgInfos.Add(ProtocolMsgSubProcessAsync(d));
            });
            await Task.WhenAll(dataMsgInfos);
            var dainfoList = dataMsgInfos.Select(d => d.Result).OrderBy(d => d.insertIndex).ToList();

            protocolModel.msgDataInfo = MontageMsgInfo(dainfoList);

            return protocolModel;
        }
        /// <summary>
        /// 合并在一帧数据中同一索引下的所有数据
        /// </summary>
        /// <param name="infos"></param>
        /// <returns></returns>
        private async Task<MsgDataInfoModel> ProtocolMsgSubProcessAsync(IGrouping<int, ProtocolEntity> infos)
        {
            MsgDataInfoModel result = new MsgDataInfoModel();
            List<Task<MsgDataInfoModel>> dataInfoList = new List<Task<MsgDataInfoModel>>();
            foreach (var item in infos)
            {
                //dataInfoList.Add(DataInfoProcess(item.isBitAnalysis, item.fieldInfo, infos.Key));
            }
            await Task.WhenAll(dataInfoList);
            var dataInfo = dataInfoList.Select(d => d.Result).OrderBy(i => i.insertIndex).ToList();

            result.insertIndex = infos.Key;
            dataInfo.ForEach(d =>
            {
                result.info += d.info;
            });
            return result;
        }
        /// <summary>
        /// 报文内容处理
        /// </summary>
        /// <param name="isBitAnalysis"></param>
        /// <param name="info"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        private async Task<MsgDataInfoModel> DataInfoProcess(bool isBitAnalysis, string info, int startIndex)
        {
            MsgDataInfoModel result = new MsgDataInfoModel();
            await Task.Run(() =>
            {
                if (!info.Contains(":"))
                {
                    result.insertIndex = startIndex;
                    result.info = info;
                }
                else
                {
                    result = isBitAnalysis ? BitInfoProcess(info, startIndex) : InfoProcess(info, startIndex);
                }
            });
            return result;
        }
        /// <summary>
        /// 按位有效报文内容处理
        /// </summary>
        /// <param name="info"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        private MsgDataInfoModel BitInfoProcess(string info, int startIndex)
        {
            MsgDataInfoModel msgDataInfoModel = new MsgDataInfoModel();

            var index = info.Substring(0, info.IndexOf(':'));
            if (index is null)
            {
                Log.Error("数据异常");
                return null;
            }
            var bitInfos = info.Substring(info.IndexOf(':') + 1).Split(new char[] { '{', ':', '}' }, StringSplitOptions.RemoveEmptyEntries);
            if (bitInfos is null || !BitInfoCheck(bitInfos, out var bitMsg))
            {
                Log.Error("位数据异常");
                return null;
            }
            var insertIndex = index.StringToIndex();
            if (!insertIndex.HasValue)
            {
                Log.Error("数据索引异常! ");
                return null;
            }
            msgDataInfoModel.insertIndex = startIndex + insertIndex.Value;
            msgDataInfoModel.info = bitMsg;
            return msgDataInfoModel;
        }

        private MsgDataInfoModel InfoProcess(string info, int startIndex)
        {
            MsgDataInfoModel msgDataInfoModel = new MsgDataInfoModel();
            var dataInfos = info.Split(':').ToList();
            if (dataInfos is null || dataInfos.Count != 2)
            {
                Log.Error("数据异常! ");
                return null;
            }
            var index = dataInfos.First().StringToIndex();
            if (!index.HasValue)
            {
                Log.Error("数据索引异常! ");
                return null;
            }
            msgDataInfoModel.insertIndex = index.Value + startIndex;
            msgDataInfoModel.info = dataInfos.LastOrDefault();
            return msgDataInfoModel;
        }
        private bool BitInfoCheck(string[] info, out string bitMsg)
        {
            bitMsg = "";
            foreach (var item in info)
            {
                if (item.Length != 4)
                {
                    return false;
                }
            }
            bitMsg = string.Join(null, info).BinaryToHex();
            return true;
        }
        /// <summary>
        /// 拼接报文内容
        /// </summary>
        /// <param name="infos"></param>
        /// <returns></returns>
        private string MontageMsgInfo(List<MsgDataInfoModel> infos)
        {
            string gengricInfo = gengricMsg;
            string result = "";
            if (string.IsNullOrEmpty(gengricMsg))
            {
                var msgInfos = infos.Select(i => i.info).ToList();
                result = string.Join(null, msgInfos);
                return result;
            }
            var msgInfoList = gengricInfo.Split(',').ToList();
            for (int i = 0; i < msgInfoList.Count; i++)
            {
                if (msgInfoList[i] == ConstStringData.InsertStringInfo)
                {
                    result += infos.Where(info => info.insertIndex == i + 1)?.FirstOrDefault()?.info;
                    continue;
                }
                result += msgInfoList[i];
            }
            return result;
        }
        #endregion
    }
}
